/**
 * can_test.c
 * 
 * CAN通信测试程序，演示如何使用CAN库发送和接收CAN消息
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "can_lib.h"

/**
 * 打印CAN消息内容
 */
void print_can_message(const can_message_t *msg)
{
    printf("CAN Message:\n");
    printf("  ID: 0x%08X\n", msg->id);
    printf("  Type: %s %s\n", 
           msg->is_extended ? "Extended Frame" : "Standard Frame",
           msg->is_remote ? "(Remote Request)" : "");
    printf("  Data Length: %d\n", msg->data_len);
    
    if (!msg->is_remote) {
        printf("  Data: ");
        for (int i = 0; i < msg->data_len; i++) {
            printf("0x%02X ", msg->data[i]);
        }
        printf("\n");
    }
}

/**
 * 发送测试消息
 */
void send_test_message(int can_fd)
{
    can_message_t msg;
    int ret;
    
    // 初始化测试消息
    memset(&msg, 0, sizeof(can_message_t));
    
    printf("\n=== Send CAN Message ===\n");
    printf("Enter CAN ID (decimal or hex with 0x prefix): ");
    scanf("%x", &msg.id);
    
    printf("Is extended frame? (0=no, 1=yes): ");
    scanf("%hhd", &msg.is_extended);
    
    printf("Is remote frame? (0=no, 1=yes): ");
    scanf("%hhd", &msg.is_remote);
    
    if (!msg.is_remote) {
        printf("Enter data length (0-8): ");
        scanf("%hhd", &msg.data_len);
        
        if (msg.data_len > 8) msg.data_len = 8;
        if (msg.data_len < 0) msg.data_len = 0;
        
        if (msg.data_len > 0) {
            printf("Enter %d data bytes (hex, space separated): ", msg.data_len);
            for (int i = 0; i < msg.data_len; i++) {
                scanf("%hhx", &msg.data[i]);
            }
        }
    }
    
    // 发送消息
    ret = can_send(can_fd, &msg);
    if (ret == CAN_SUCCESS) {
        printf("Message sent successfully!\n");
        print_can_message(&msg);
    } else {
        printf("Failed to send message: %s\n", can_get_error_string(ret));
    }
}

/**
 * 接收CAN消息
 */
void receive_messages(int can_fd)
{
    can_message_t msg;
    int ret;
    int timeout;
    
    printf("\n=== Receive CAN Messages ===\n");
    printf("Enter receive timeout in milliseconds (0=non-blocking, -1=infinite): ");
    scanf("%d", &timeout);
    
    printf("Waiting for CAN messages... (Press Ctrl+C to stop)\n");
    
    while (1) {
        ret = can_receive(can_fd, &msg, timeout);
        if (ret == CAN_SUCCESS) {
            printf("\nMessage received!\n");
            print_can_message(&msg);
        } else if (timeout == 0) {
            // 非阻塞模式，继续
            usleep(100000); // 100ms延迟
        } else {
            printf("Receive error: %s\n", can_get_error_string(ret));
            break;
        }
    }
}

/**
 * 运行循环发送测试
 */
void run_loopback_test(int can_fd)
{
    can_message_t send_msg, recv_msg;
    int ret;
    int count;
    int delay;
    
    printf("\n=== CAN Loopback Test ===\n");
    printf("Enter number of messages to send: ");
    scanf("%d", &count);
    
    printf("Enter delay between messages (ms): ");
    scanf("%d", &delay);
    
    // 初始化测试消息
    memset(&send_msg, 0, sizeof(can_message_t));
    send_msg.id = 0x123;
    send_msg.is_extended = 0;
    send_msg.is_remote = 0;
    send_msg.data_len = 8;
    
    for (int i = 0; i < 8; i++) {
        send_msg.data[i] = i;
    }
    
    printf("Starting loopback test...\n");
    
    for (int i = 0; i < count; i++) {
        // 更新发送数据
        send_msg.data[0] = (uint8_t)(i & 0xFF);
        send_msg.data[1] = (uint8_t)((i >> 8) & 0xFF);
        
        // 发送消息
        ret = can_send(can_fd, &send_msg);
        if (ret == CAN_SUCCESS) {
            printf("Sent message %d\n", i + 1);
            
            // 尝试立即接收
            ret = can_receive(can_fd, &recv_msg, 100);
            if (ret == CAN_SUCCESS) {
                printf("Received echo message\n");
            }
        } else {
            printf("Failed to send message %d: %s\n", 
                   i + 1, can_get_error_string(ret));
        }
        
        // 延时
        usleep(delay * 1000);
    }
    
    printf("Loopback test completed.\n");
}

/**
 * 显示帮助菜单
 */
void show_menu(void)
{
    printf("\n========== CAN Test Program ==========\n");
    printf("1. Send a CAN message\n");
    printf("2. Receive CAN messages\n");
    printf("3. Run loopback test\n");
    printf("4. Exit\n");
    printf("======================================\n");
    printf("Enter your choice: ");
}

int main(int argc, char *argv[])
{
    int can_fd;
    int choice;
    char interface[20] = DEFAULT_CAN_INTERFACE;
    uint32_t baud_rate = CAN_BAUD_500K; // 默认波特率500K
    
    // 解析命令行参数
    if (argc > 1) {
        strncpy(interface, argv[1], sizeof(interface) - 1);
    }
    
    if (argc > 2) {
        baud_rate = atoi(argv[2]);
        
        // 验证波特率
        switch (baud_rate) {
            case CAN_BAUD_125K:
            case CAN_BAUD_250K:
            case CAN_BAUD_500K:
            case CAN_BAUD_1M:
                break;
            default:
                printf("Warning: Invalid baud rate, using 500K instead\n");
                baud_rate = CAN_BAUD_500K;
                break;
        }
    }
    
    printf("CAN Test Program\n");
    printf("Using interface: %s\n", interface);
    printf("Baud rate: %d\n", baud_rate);
    
    // 初始化CAN接口
    can_fd = can_init(interface, baud_rate);
    if (can_fd < 0) {
        printf("Failed to initialize CAN interface: %s\n", 
               can_get_error_string(can_fd));
        printf("Please make sure the CAN interface is properly configured.\n");
        printf("You may need to run: sudo ip link set %s up type can bitrate %d\n", 
               interface, baud_rate);
        return 1;
    }
    
    printf("CAN interface initialized successfully.\n");
    
    // 主菜单循环
    while (1) {
        show_menu();
        scanf("%d", &choice);
        
        switch (choice) {
            case 1:
                send_test_message(can_fd);
                break;
            case 2:
                receive_messages(can_fd);
                break;
            case 3:
                run_loopback_test(can_fd);
                break;
            case 4:
                printf("Exiting program...\n");
                can_close(can_fd);
                return 0;
            default:
                printf("Invalid choice, please try again.\n");
                break;
        }
    }
    
    // 程序不应该到达这里
    can_close(can_fd);
    return 0;
}